/*****************************************************************//**
 * \file   Define.cpp
 * \brief  Define
 *
 * \author Wyatt
 * \date   May 2023
 *********************************************************************/
#pragma once

#include <vector>
#include <string>
#include <type_traits>
#include <algorithm>
#include <limits.h>
#include <float.h>

#include "Num3.h"

typedef unsigned long SKey;

#define DEFAUL_DBL         DBL_MAX
#define DEFAUL_FLT         FLT_MAX
#define DEFAUL_INT         INT_MAX

typedef std::vector<int>                        IdVec;
typedef std::vector<float>                      FVec;
typedef std::vector<double>                     DVec;
typedef std::vector<std::vector<int>>           IdVVec;
typedef std::vector<std::string>                StringVec;

//template <std::integral T>
//bool isDefault(T val, bool zeroIsDefault = false) {
//	return (val == INT_MAX || val == DBL_MAX || val == FLT_MAX) ? true : false;
//}

template <typename T>
bool isDefault(T val, bool zeroIsDefault = false) {
	if (std::is_integral<T>::value)
	{
		return (val == INT_MAX || val == DBL_MAX || val == FLT_MAX) ? true : false;
	}
	else
	{
		if (zeroIsDefault) { if (fabs(val) < 1e3 * DBL_MIN) return true; }
		if (fabs(val) > (1e-3 * DBL_MAX) || (fabs(val) < (1e3 * DBL_MIN) && fabs(val) > 0.0)) return true;
	}

	return false;
}

template <typename T>
typename std::enable_if<std::is_same<T, SNum3d>::value, bool>::type
isDefault(T& val, bool zeroIsDefault = false) {
	if (isDefault(val[0], zeroIsDefault) && isDefault(val[1], zeroIsDefault) && isDefault(val[2], zeroIsDefault)) return true;
	return false;
}

template <typename T>
typename std::enable_if<std::is_same<T, std::vector<double>>::value, bool>::type
isDefault(T& val, bool zeroIsDefault = false) {
	for (int i = 0; i < val.size(); i++) {
		if (!isDefault(val[i], zeroIsDefault)) return false;
	}
	return true;
}

template <typename ST>
inline ST& toUpper(ST& s) {
	std::transform(s.cbegin(), s.cend(), s.begin(), ::toupper);
	return s;
}

template <typename ST>
inline ST&& toUpper(ST&& s) {
	std::transform(s.cbegin(), s.cend(), s.begin(), toupper);
	return std::move(s);
}
